/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef OHOS_AVPLAYBACK_STATE_H
#define OHOS_AVPLAYBACK_STATE_H

/**
 * @addtogroup avsession
 * @{
 *
 * @brief 音视频媒体会话，提供系统内媒体的统一控制能力。
 *
 * 功能包括媒体会话，媒体会话管理，媒体会话控制。
 *
 * @syscap SystemCapability.Multimedia.AVSession.Core
 * @since 9
 * @version 1.0
 */

/**
 * @file avplayback_state.h
 *
 * @brief 音视频播放状态声明。
 *
 * @since 9
 * @version 1.0
 */

#include <bitset>
#include <parcel.h>

namespace OHOS::AVSession {
/**
 * @brief 音视频播放状态类，提供获取和设置播放界面的信息。
 */
class AVPlaybackState : public Parcelable {
public:

    /**
     * @brief 描述播放状态的枚举。
     *
     */
    enum {
        /** 初始状态*/
        PLAYBACK_STATE_INITIAL = 0,
        /** 缓冲状态*/
        PLAYBACK_STATE_PREPARING = 1,
        /** 播放状态*/
        PLAYBACK_STATE_PLAYING = 2,
        /** 暂停状态*/
        PLAYBACK_STATE_PAUSED = 3,
        /** 快进状态*/
        PLAYBACK_STATE_FAST_FORWARD = 4,
        /** 快退状态*/
        PLAYBACK_STATE_REWIND = 5,
        /** 停止状态*/
        PLAYBACK_STATE_STOP = 6,
        /** 无效类型，内部用于判断状态是否有效 */
        PLAYBACK_STATE_MAX = 7
    };

    /**
     * @brief 播放界面信息的枚举。
     *
     */
    enum {
        /** 播放状态，包括正在播放、暂停、快进等*/
        PLAYBACK_KEY_STATE = 0,
        /** 播放倍数*/
        PLAYBACK_KEY_SPEED = 1,
        /** 播放位置*/
        PLAYBACK_KEY_POSITION = 2,
        /** 缓冲时间*/
        PLAYBACK_KEY_BUFFERED_TIME = 3,
        /** 循环模式*/
        PLAYBACK_KEY_LOOP_MODE = 4,
        /** 设置喜欢(收藏)*/
        PLAYBACK_KEY_IS_FAVORITE = 5,
        /** 无效类型，内部用于判断key是否有效 */
        PLAYBACK_KEY_MAX = 6
    };

    /**
     * @brief 循环模式的枚举。
     *
     */
    enum {
        /** 顺序播放*/
        LOOP_MODE_SEQUENCE = 0,
        /** 单曲循环*/
        LOOP_MODE_SINGLE = 1,
        /** 列表循环*/
        LOOP_MODE_LIST = 2,
        /** 随机播放*/
        LOOP_MODE_SHUFFLE = 3
    };

    /**
     * @brief 播放位置的相关信息。
     *
     * @since 9
     * @version 1.0
     */
    struct Position {
        /** 媒体已经播放的时间点，第x ms，单位为ms */
        int64_t elapsedTime_ {};
        /** 更新的时间戳，单位为ms */
        int64_t updateTime_ {};
    };

    using PlaybackStateMaskType = std::bitset<PLAYBACK_KEY_MAX>;

    AVPlaybackState();
    ~AVPlaybackState() override = default;

    /**
     * @brief IPC通信数据反序列化。
     *
     * 将通过IPC接收的{@link Parcel}类型的信息，反序列化为AVPlaybackState类型的信息。
     *
     * @param parcel 序列化对象{@link Parcel}。
     * @return 如果反序列化成功，则返回AVPlaybackState对象;
     *         如果反序列化失败，则返回nullptr。
     * @see Marshalling
     * @since 9
     * @version 1.0
     */
    static AVPlaybackState* Unmarshalling(Parcel& parcel);

    /**
     * @brief IPC通信数据序列化。
     *
     * 将AVPlaybackState类型的信息，序列化为{@link Parcel}类型的信息，用来进行IPC通信。
     *
     * @param parcel 保存序列化值的对象{@link Parcel}。
     * @return 成功返回true；失败返回false。
     * @see Unmarshalling
     * @since 9
     * @version 1.0
     */
    bool Marshalling(Parcel& parcel) const override;

    /**
     * @brief 验证当前信息的有效性。
     *
     * @return 有效返回true；无效则返回false。
     * @since 9
     * @version 1.0
     */
    bool IsValid() const;

    /**
     * @brief 设置音视频的播放状态。
     *
     * @param state 音视频的播放状态，范围{@link #PLAYBACK_STATE_INITIAL}到{@link #PLAYBACK_STATE_MAX}之间。
     * @see GetState
     * @since 9
     * @version 1.0
     */
    void SetState(int32_t state);

    /**
     * @brief 获取当前音视频的播放状态。
     *
     * @return 返回当前音视频的播放状态，范围{@link #PLAYBACK_STATE_INITIAL}到{@link #PLAYBACK_STATE_MAX}之间。
     * @see SetState
     * @since 9
     * @version 1.0
     */
    int32_t GetState() const;

    /**
     * @brief 设置播放倍速。
     *
     * @param speed 播放倍速。
     * @see SetSpeed
     * @since 9
     * @version 1.0
     */
    void SetSpeed(double speed);

    /**
     * @brief 获取当前播放倍速。
     *
     * @return 返回当前播放倍速。
     * @see SetSpeed
     * @since 9
     * @version 1.0
     */
    double GetSpeed() const;

    /**
     * @brief 设置播放位置，通过更新时间与经过时间来计算，单位ms。
     *
     * @param position 播放位置{@link Position}。
     * @see GetPosition
     * @since 9
     * @version 1.0
     */
    void SetPosition(const Position& position);

    /**
     * @brief 获取播放位置。
     *
     * @return 返回播放位置{@link Position}。
     * @see SetPosition
     * @since 9
     * @version 1.0
     */
    Position GetPosition() const;

    /**
     * @brief 设置缓冲时间，单位为ms。
     *
     * @param time 缓冲时间。
     * @see GetBufferedTime
     * @since 9
     * @version 1.0
     */
    void SetBufferedTime(int64_t time);

    /**
     * @brief 获取当前缓冲时间，单位为ms。
     *
     * @return 返回缓冲时间。
     * @see SetBufferedTime
     * @since 9
     * @version 1.0
     */
    int64_t GetBufferedTime() const;

    /**
     * @brief 设置循环模式。
     *
     * @param mode 循环模式，范围{@link #LOOP_MODE_SEQUENCE}到{@link #LOOP_MODE_SHUFFLE}之间。
     * @see GetLoopMode
     * @since 9
     * @version 1.0
     */
    void SetLoopMode(int32_t mode);

    /**
     * @brief 获取当前循环模式。
     *
     * @return 返回循环模式，范围{@link #LOOP_MODE_SEQUENCE}到{@link #LOOP_MODE_SHUFFLE}之间。
     * @see SetLoopMode
     * @since 9
     * @version 1.0
     */
    int32_t GetLoopMode() const;

    /**
     * @brief 设置是否收藏。
     *
     * @param isFavorite 是否收藏，是则为true，否则false。
     * @see GetFavorite
     * @since 9
     * @version 1.0
     */
    void SetFavorite(bool isFavorite);

    /**
     * @brief 获取是否收藏。
     *
     * @return 是否收藏，是则返回true，否则返回false。
     * @see SetFavorite
     * @since 9
     * @version 1.0
     */
    bool GetFavorite() const;

    /**
     * @brief 获取掩码。
     *
     * @return 返回播放界面信息的掩码{@link PlaybackStateMaskType}。
     * @see CopyFrom
     * @since 9
     * @version 1.0
     */
    PlaybackStateMaskType GetMask() const;

    /**
     * @brief 通过掩码拷贝信息到新的AVPlaybackState对象。
     *
     * mask对应位上有值的对象拷贝给out。
     *
     * @param mask 输入的掩码@{@link PlaybackStateMaskType}。
     * @param out 输出的音视频的播放状态{@link AVPlaybackState}。
     * @return 如果有至少一个播放界面信息被拷贝，返回true；如果一个播放界面信息都没有被拷贝，返回false。
     * @see CopyFrom
     * @since 9
     * @version 1.0
     */
    bool CopyToByMask(PlaybackStateMaskType& mask, AVPlaybackState& out) const;

    /**
     * @brief 根据当前对象的mask_掩码，将输入的AVPlaybackState类型的信息复制到当前对象。
     *
     * @param in AVPlaybackState类型的引用{@link AVPlaybackState}。
     * @return 如果有至少一个播放界面信息被拷贝，返回true；如果一个播放界面信息都没有被拷贝，返回false。
     * @see CopyToByMask
     * @see GetMask
     * @since 9
     * @version 1.0
     */
    bool CopyFrom(const AVPlaybackState& in);
    
    /**
     * @brief 内联函数指针数组{@link AVPlaybackState}，用于分布式业务，设置播放界面信息。
     *
     * @since 9
     * @version 1.0
     */
    const static inline std::vector<int32_t> localCapability {
        PLAYBACK_KEY_STATE,
        PLAYBACK_KEY_SPEED,
        PLAYBACK_KEY_POSITION,
        PLAYBACK_KEY_BUFFERED_TIME,
        PLAYBACK_KEY_LOOP_MODE,
        PLAYBACK_KEY_IS_FAVORITE,
    };

private:

    /**
     * @brief 播放界面信息的掩码。
     *
     * 对应位置的掩码为1，就说明当前对象包含了这项界面信息{@link PlaybackStateMaskType}。
     */
    PlaybackStateMaskType mask_;

    /**
     * @brief 音视频的播放状态{@link #PLAYBACK_STATE_INITIAL}。
     *
     */
    int32_t state_ = PLAYBACK_STATE_INITIAL;

    /**
     * @brief 播放倍速。
     *
     */
    double speed_ = 1.0;

    /**
     * @brief 播放位置{@link Position}。
     *
     */
    Position position_;

    /**
     * @brief 缓冲时间。
     *
     */
    int64_t bufferedTime_ {};

    /**
     * @brief 循环模式{@link #LOOP_MODE_SEQUENCE}。
     *
     */
    int32_t loopMode_ = LOOP_MODE_SEQUENCE;

    /**
     * @brief 是否收藏。
     *
     */
    bool isFavorite_ {};

    /**
     * @brief 拷贝音视频的播放状态信息。
     *
     * @param from 源{@link AVPlaybackState}。
     * @param to 目标{@link AVPlaybackState}。
     * @since 9
     * @version 1.0
     */
    static void CloneState(const AVPlaybackState& from, AVPlaybackState& to);

    /**
     * @brief 拷贝播放倍速的信息。
     *
     * @param from 源{@link AVPlaybackState}。
     * @param to 目标{@link AVPlaybackState}。
     * @since 9
     * @version 1.0
     */
    static void CloneSpeed(const AVPlaybackState& from, AVPlaybackState& to);

    /**
     * @brief 拷贝播放位置的信息。
     *
     * @param from 源{@link AVPlaybackState}。
     * @param to 目标{@link AVPlaybackState}。
     * @since 9
     * @version 1.0
     */
    static void ClonePosition(const AVPlaybackState& from, AVPlaybackState& to);

    /**
     * @brief 拷贝缓冲时间的信息法。
     *
     * @param from 源{@link AVPlaybackState}。
     * @param to 目标{@link AVPlaybackState}。
     * @since 9
     * @version 1.0
     */
    static void CloneBufferedTime(const AVPlaybackState& from, AVPlaybackState& to);

    /**
     * @brief 拷贝循环模式的信息。
     *
     * @param from 源{@link AVPlaybackState}。
     * @param to 目标{@link AVPlaybackState}。
     * @since 9
     * @version 1.0
     */
    static void CloneLoopMode(const AVPlaybackState& from, AVPlaybackState& to);

    /**
     * @brief 拷贝是否喜欢的信息。
     *
     * @param from 源{@link AVPlaybackState}。
     * @param to 目标{@link AVPlaybackState}。
     * @since 9
     * @version 1.0
     */
    static void CloneIsFavorite(const AVPlaybackState& from, AVPlaybackState& to);

    /**
     * @brief 定义拷贝信息的函数指针。
     *
     * @param from 源{@link AVPlaybackState}。
     * @param to 目标{@link AVPlaybackState}。
     * @since 9
     * @version 1.0
     */
    using CloneActionType = void(*)(const AVPlaybackState& from, AVPlaybackState& to);

    /**
     * @brief 内联函数指针数组{@link AVPlaybackState}, {@link CloneActionType}。
     *
     * 通过访问cloneActions[i]来调用对应的拷贝函数。
     *
     */
    static inline CloneActionType cloneActions[PLAYBACK_KEY_MAX] = {
        [PLAYBACK_KEY_STATE] = &AVPlaybackState::CloneState,
        [PLAYBACK_KEY_SPEED] = &AVPlaybackState::CloneSpeed,
        [PLAYBACK_KEY_POSITION] = &AVPlaybackState::ClonePosition,
        [PLAYBACK_KEY_BUFFERED_TIME] = &AVPlaybackState::CloneBufferedTime,
        [PLAYBACK_KEY_LOOP_MODE] = &AVPlaybackState::CloneLoopMode,
        [PLAYBACK_KEY_IS_FAVORITE] = &AVPlaybackState::CloneIsFavorite,
    };
};
} // namespace OHOS::AVSession
/** @} */
#endif // OHOS_AVPLAYBACK_STATE_H